﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using DevExpress.Skins;

namespace SVNClean.Modules {
    public static class Extensions {

        /// <summary>
        /// Determines whether [is SVN directory] [the specified dir].
        /// </summary>
        /// <param name="dir">The dir.</param>
        /// <returns>
        /// 	<c>true</c> if [is SVN directory] [the specified dir]; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsSvnDirectory(this DirectoryInfo dir) {
            if (dir != null && dir.Exists) {
                return dir.Name.IsSvnDirectory();
            }
            return false;
        }

        /// <summary>
        /// Determines whether [contains VS projects] [the specified dir].
        /// </summary>
        /// <param name="dir">The dir.</param>
        /// <returns>
        /// 	<c>true</c> if [contains VS projects] [the specified dir]; otherwise, <c>false</c>.
        /// </returns>
        public static bool ContainsVSProjects(this DirectoryInfo dir) {
            if (dir != null) {
                dir.Refresh();
                if (dir.Exists) {
                    var files = dir.GetFiles();
                    foreach (var file in files) {
                        if (file.Extension == ".csproj" || file.Extension == ".vbproj" ||
                            file.Extension == ".cpproj" || file.Extension == ".jsproj" ||
                            file.Extension == ".sln") {
                            return true;
                        }
                    }
                }
            }
            return false;
        }


        /// <summary>
        /// Determines whether the specified dir is drive.
        /// </summary>
        /// <param name="dir">The dir.</param>
        /// <returns>
        /// 	<c>true</c> if the specified dir is drive; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsDrive(this DirectoryInfo dir) {
            if (dir != null) {
                var drives = new List<string>(Directory.GetLogicalDrives());
                return drives.Contains(dir.Name);
            }
            return false;
        }

        /// <summary>
        /// Determines whether the specified dir is file.
        /// </summary>
        /// <param name="dir">The dir.</param>
        /// <returns>
        /// 	<c>true</c> if the specified dir is file; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsFile(this DirectoryInfo dir) {
            if (dir != null) {
                return (dir.Attributes & FileAttributes.Directory) == 0;
            }
            return false;
        }

        /// <summary>
        /// Gets the directory path.
        /// </summary>
        /// <param name="info">The info.</param>
        /// <returns></returns>
        public static string GetDirectoryPath(this DirectoryInfo info) {
            if (info.IsFile()) {
                return info.FullName.Replace("\\" + info.Name, "");
            }
            return info.FullName;
        }

        /// <summary>
        /// Gets the directory path info.
        /// </summary>
        /// <param name="info">The info.</param>
        /// <returns></returns>
        public static DirectoryInfo GetDirectoryPathInfo(this DirectoryInfo info) {
            return new DirectoryInfo(GetDirectoryPath(info));
        }

        /// <summary>
        /// Fills the left zeros.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="length">The length.</param>
        /// <returns></returns>
        public static string FillLeftZeros(this int value, int length) {
            string strvalue = value.ToString();
            string strleftz = "";
            for (int i = strvalue.Length; i < length; i++) {
                strleftz += "0";
            }
            return strleftz + strvalue;
        }

        /// <summary>
        /// Fills the left spaces.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="length">The length.</param>
        /// <returns></returns>
        public static string FillLeftSpaces(this Version value, int length) {
            string strvalue = value.ToString();
            string strleftz = "";
            for (int i = strvalue.Length; i < length; i++) {
                strleftz += " ";
            }
            return strvalue + strleftz;
        }

        /// <summary>
        /// Serializes the specified obj.
        /// </summary>
        /// <param name="obj">The obj.</param>
        /// <returns></returns>
        public static string Serialize(this object obj) {
            if (obj != null) {
                var serializer = new XmlSerializer(obj.GetType());
                var xmlContent = new StringBuilder();
                var writer = XmlWriter.Create(xmlContent);
                if (writer == null) return "";
                serializer.Serialize(writer, obj);
                return xmlContent.ToString();
            }
            throw new NullReferenceException();
        }

        /// <summary>
        /// Deserializes the specified XML.
        /// </summary>
        /// <param name="xml">The XML.</param>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        public static object Deserialize(this string xml, Type type) {
            var serializer = new XmlSerializer(type);
            if (serializer.CanDeserialize(XmlReader.Create(new StringReader(xml)))) {
                return serializer.Deserialize(new StringReader(xml));
            }
            throw new FormatException();
        }

        /// <summary>
        /// Gets the build date.
        /// </summary>
        /// <param name="asm">The asm.</param>
        /// <returns></returns>
        public static DateTime GetBuildDate(this AssemblyName asm) {
            return new System.DateTime(2000, 1, 1).AddDays(asm.Version.Build);
        }

        /// <summary>
        /// Gets the short name of the path.
        /// </summary>
        /// <param name="path">The path.</param>
        /// <returns></returns>
        public static string GetShortPathName(string path) {
            try {
                var parts = new List<string>(path.Split(new char[] { Convert.ToChar("\\") }, StringSplitOptions.RemoveEmptyEntries));
                if (parts.Count >= 5) {
                    string file = Path.GetFileName(path);
                    return string.Concat(parts[0], "\\", parts[1], "\\...\\", parts[parts.Count - 2], "\\", file);
                }
                return path;
            }
            catch (Exception) { Debugger.Break(); return path; }
        }

        /// <summary>
        /// Gets the short name of the path.
        /// </summary>
        /// <param name="dir">The dir.</param>
        /// <returns></returns>
        public static string GetShortPathName(this DirectoryInfo dir) {
            return GetShortPathName(dir.FullName);
        }

        /// <summary>
        /// Gets the short name of the path.
        /// </summary>
        /// <param name="dir">The dir.</param>
        /// <returns></returns>
        public static string GetShortPathName(this FileInfo dir) {
            return GetShortPathName(dir.FullName);
        }

        /// <summary>
        /// Gets the available skins.
        /// </summary>
        /// <returns></returns>
        public static string GetAvailableSkins() {
            string result = "\n\n";
            foreach (SkinContainer cnt in SkinManager.Default.Skins) {
                result += cnt.SkinName + "\n";
            }
            return result;
        }
    }
}
